package future;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 电商各平台价格比较案例
 * <pre>
 * 4.1 需求描述
 *    1. 查询同一款商品在不同电商平台上的售价。
 *    2. 查询同一款商品在同一平台下，各个入驻卖家的售价。\
 * 4.2 输出结果
 * 例如查询同一商品在不同平台下的售价，返回一个List<String>,示例如下：
 *
 * 《Mysql》在淘宝上售价85.8元
 * 《Mysql》在京东上售价95.9元
 * 《Mysql》在当当上售价93.8元
 *
 * 4.3 解决方案
 * step by step：一个一个查询，效率较低。
 * all in：并行查询，效率较高。
 * </pre>
 *
 * @author codefish
 * @version 1.0
 * @date 2022/07/28 下午 05:23
 */
public class ComparePriceCase {
    List<NetMall> mallList;


    @Test
    public void runTest() throws Exception {
        System.out.println("-------------------------------------");
        long stime = System.currentTimeMillis();
        List<String> priceList = getPrices("MySQL");
        priceList.forEach(System.out::println);
        long etime = System.currentTimeMillis();
        System.out.println("---costTime：" + (etime - stime) + "ms");
        System.out.println("-------------------------------------");
        long stime2 = System.currentTimeMillis();
        List<String> priceList2 = getPricesParallel("MySQL");
        priceList2.forEach(System.out::println);
        long etime2 = System.currentTimeMillis();
        System.out.println("---costTime：" + (etime2 - stime2) + "ms");
        System.out.println("-------------------------------------");
    }

    //step by step
    List<String> getPrices(String productName) {
        List<String> result = mallList.stream()
                .map(mall ->
                        String.format("%s在%s的售价为%.2f元",
                                productName,
                                mall.getMallName(),
                                mall.queryPrice(productName)
                        ))
                .collect(Collectors.toList());
        return result;
    }

    //Parallel(all in)
    List<String> getPricesParallel(String productName) throws Exception {
        List<String> list =
                mallList.stream()
                        .map(mall ->
                                CompletableFuture.supplyAsync(() ->
                                        String.format("%s在%s的售价为%.2f元",
                                                productName,
                                                mall.getMallName(),
                                                mall.queryPrice(productName)
                                        )))
                        .collect(Collectors.toList())
                        .stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList());
        return list;

    }


    @Before
    public void init() {
        mallList = new ArrayList<>();
        mallList.add(new NetMall("jd"));
        mallList.add(new NetMall("taobao"));
        mallList.add(new NetMall("dangdang"));
    }


    //电商平台类
    @AllArgsConstructor
    private class NetMall {
        //平台名
        @Getter
        String mallName;

        //模拟查询商品价格
        public double queryPrice(String productName) {
            //模拟查询耗时操作，休眠1s
            try {
                TimeUnit.MILLISECONDS.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
        }

    }
}
